package bupt.xixi.registry.impl;

import bupt.xixi.enumeration.BalancerType;
import bupt.xixi.loadbalancer.LoaderBalancer;
import bupt.xixi.loadbalancer.LoaderBalancerFactory;
import bupt.xixi.registry.IServiceDiscovery;
import lombok.extern.slf4j.Slf4j;

import javax.naming.NameNotFoundException;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
abstract public class AbstractDiscovery implements IServiceDiscovery {

    // todo: 参数是重复的, 可以设置到common里
    protected static final int BASE_SLEEP_TIME = 1000;
    protected static final int MAX_RETRIES = 3;

    private final Set<String> CACHE_REGISTERED_PATH_SET = ConcurrentHashMap.newKeySet(); // todo 没用,可删 记录所有注册过的服务
    protected Map<String, List<String>> CACHE_SERVICE_ADDRESS_MAP = new ConcurrentHashMap<>();

    // 设置负载局衡器
    private static final BalancerType BALANCE = BalancerType.ROUND_ROBIN_BALANCER;
    private final LoaderBalancer balancer = LoaderBalancerFactory.getBalancer(BALANCE.getCode());

    @Override
    public InetSocketAddress lookupService(String serviceName) {
        List<String> result = null;
        if (CACHE_SERVICE_ADDRESS_MAP.containsKey(serviceName)) {
            // 1. 先在缓存中查找
            result = CACHE_SERVICE_ADDRESS_MAP.get(serviceName);
        } else {
            // 2. 缓存中没有, 调用ZK找
            result = doLookupService(serviceName);
        }
        if (result.isEmpty()) {
            NameNotFoundException exception = new NameNotFoundException("找不到指定的服务");
            exception.printStackTrace();
        }
        // 3. 负载均衡来一套
        String socket = balancer.select(result);
        String hostname = socket.split(":")[0];
        int port = Integer.parseInt(socket.split(":")[1]);
        return new InetSocketAddress(hostname, port);
    }

    protected abstract List<String> doLookupService(String serviceName);
}
